package com.cms.service.impl;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.cms.common.hibernate.BaseDao;
import com.cms.service.MyBaseService;

@Service
@Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRED)
public class MyBaseServiceImpl implements MyBaseService {
	@Autowired
	@Qualifier("baseDao")
	protected BaseDao baseDao;

	@Override
	public Object get(Class<?> clazz, Long id) {
		return baseDao.get(clazz, id);
	}

	@Override
	public Object getByProperty(Class<?> clazz, String property, String value) {
		return baseDao.getByProperty(clazz, property, value);
	}

	/** 增加或更新实体. */
	public void saveOrUpdate(Object entity) {
		try {
			Method method = entity.getClass().getMethod("updateDate");
			method.invoke(entity);
			baseDao.saveOrUpdate(entity);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/** 删除指定的实体. */
	public void delete(Object entity) {
		baseDao.delete(entity);
	}

	/** 删除指定的实体. */
	public void deleteById(Class<?> clazz, Long id) {
		baseDao.delete(baseDao.get(clazz, id));
	}

	@Override
	public Long countByExample(Object exampleEntity) {
		List<Criterion> any = new ArrayList<Criterion>();
		Field[] fields = exampleEntity.getClass().getDeclaredFields();
		for (Field field : fields) {
			Method method = null;
			Object value = null;
			String name = field.getName();
			String getMethod = "get" + name.substring(0, 1).toUpperCase()
					+ name.substring(1);
			try {
				method = exampleEntity.getClass().getMethod(getMethod);
				value = method.invoke(exampleEntity);
				if (value != null) {// 如果值不为空则加入查询条件
					if (name.contains("_like")) {// 以_like结尾的为模糊查询
						any.add(Restrictions.like(name.replace("_like", ""),
								value.toString(), MatchMode.ANYWHERE));
					} else if (name.contains("_start")) {
						any.add(Restrictions.ge(name.replace("_start", ""),
								value));
					} else if (name.contains("_end")) {
						any.add(Restrictions.le(name.replace("_end", ""), value));
					} else {
						any.add(Restrictions.eq(name, value));
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return baseDao.countByAny(exampleEntity.getClass(),
				any.toArray(new Criterion[any.size()]));
	}

	@Override
	public <T> List<T> listByExample(T exampleEntity, Integer from, Integer to) {
		// 查询参数
		List<Object> any = new ArrayList<Object>();
		any.add(Transformers.aliasToBean(exampleEntity.getClass()));
		Field[] cFields = exampleEntity.getClass().getDeclaredFields();
		Field[] pFields = exampleEntity.getClass().getSuperclass()
				.getDeclaredFields();
		List<Field> fields = new LinkedList<Field>();
		fields.addAll(Arrays.asList(cFields));
		fields.addAll(Arrays.asList(pFields));
		for (Field field : fields) {
			Method method = null;
			Object value = null;
			String name = field.getName();
			String getMethod = "get" + name.substring(0, 1).toUpperCase()
					+ name.substring(1);
			if (!name.contains("_like") && !name.contains("_start")
					&& !name.contains("_end")) {
				any.add(Projections.property(name).as(name));// 加入查询返回字段
			}
			try {
				method = exampleEntity.getClass().getMethod(getMethod);
				value = method.invoke(exampleEntity);
				if (value != null) {// 如果值不为空则加入查询条件
					if (name.contains("_like")) {// 以_like结尾的为模糊查询
						any.add(Restrictions.like(name.replace("_like", ""),
								value.toString(), MatchMode.ANYWHERE));
					} else if (name.contains("_start")) {
						any.add(Restrictions.ge(name.replace("_start", ""),
								value));
					} else if (name.contains("_end")) {
						any.add(Restrictions.le(name.replace("_end", ""), value));
					} else {
						any.add(Restrictions.eq(name, value));
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		any.add(Order.desc("createDate"));
		return baseDao.findByAny(exampleEntity.getClass(), from, to,
				any.toArray());
	}

	@Override
	public void updateByX(String hql, Object... objects) {
		baseDao.hqlUpdate(hql, objects);
	}

}
